import dayjs from 'dayjs'
import NP from 'number-precision'
import customParseFormat from 'dayjs/plugin/customParseFormat'
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'
import minMax from 'dayjs/plugin/minMax'
import { FULL_DAY_TIME, FULL_HALF_DAY_TIME } from '../enums/attendance'
import type { AttendanceExcelItem } from '../types/attendance'

// 加载插件
dayjs.extend(customParseFormat)
dayjs.extend(isSameOrBefore)
dayjs.extend(minMax)

/**
 * 更改数组所有的KEY名
 * @param arr 原数组
 * @param keyMap key映射表
 * @return 新数组
 */
export function modifyArrKeyName<U extends Record<string, any>>(
  arr: Record<string, any>[],
  keyMap: Record<string, string>,
): U[] {
  return arr.map((item) => {
    const newItem: any = {}
    for (const oldKey in item) {
      if (item[oldKey]) {
        const newKey = keyMap[oldKey]
        newItem[newKey] = item[oldKey]
      }
      else {
        newItem[oldKey] = item[oldKey]
      }
    }
    return newItem
  })
}

export function filterAttendanceData(record: AttendanceExcelItem) {
  const filter_1 = ['成辉'].includes(record.employeeName)
  const conditions = [!filter_1]
  return conditions.some(condition => condition)
}

/**
 * 保证半个小时为维度的分钟数
 * @param num 原分钟
 * @return 处理后的分钟数
 */
export function makeEven(num: number) {
  return num -= num % 30
}

/**
 * 将时间转成 24 小时制。
 * @param time 时间
 * @return 是否有效
 */
export function convertTo24Hour(time: string | undefined): string {
  if (!time)
    return ''
  const [timePart, modifier] = time.split(' ')
  const [hoursStr, minutesStr] = timePart.split(':')

  // 将小时转换为数字
  let hours = Number.parseInt(hoursStr, 10)
  const minutes = Number.parseInt(minutesStr, 10)

  // 根据AM或PM调整小时
  if (modifier === 'PM' && hours !== 12) {
    hours = (hours % 12 + 12)
  }
  else if (modifier === 'AM' && hours === 12) {
    hours = 0
  }

  // 格式化为两位数
  return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`
}

/**
 * 计算当天上班的上班时间是否在弹性的上班有效期内
   上午休假：下午两点之前打卡有效
   下午休假：上午九点半之前打卡有效
 * @param workday 出勤日期
 * @param checkStartTime 开始打卡时间
 * @param isPM 下午开始打卡
 * @return 是否有效
 */
export function isEffectStartWorkTime(workday: string, checkStartTime: string | undefined, isPM: boolean): boolean {
  checkStartTime = convertTo24Hour(checkStartTime)
  const now = dayjs(`${workday} ${checkStartTime}`)

  const endAM = now.startOf('day').hour(9).minute(30)

  const endPM = now.startOf('day').hour(14).minute(0)

  const isInRange = !isPM ? now.isSameOrBefore(endAM) : (now.isSameOrBefore(endPM))
  return isInRange
}

/**
 * 计算一天在职时间
 * @param workday 出勤日期
 * @param checkStartTime 上班打卡时间
 * @param checkEndTime 下班班打卡时间
 * @return 是否有效
 */
export function getWorkAllTime(workday: string, checkStartTime: string | undefined, checkEndTime: string | undefined, isPM: boolean): number {
  checkStartTime = convertTo24Hour(checkStartTime)
  checkEndTime = convertTo24Hour(checkEndTime)

  let start = dayjs(`${workday} ${checkStartTime}`)
  const end = dayjs(`${workday} ${checkEndTime}`)

  if (isPM) { // 只有下午上班
    start = dayjs.max(start, dayjs(`${workday} 13:30:00`))
  }
  else {
    start = dayjs.max(start, dayjs(`${workday} 8:30:00`))
  }

  const durationInMinutes = end.diff(start, 'minute')

  return durationInMinutes
}

/**
 * 计算一天在职时间是否有效
 * @param workday 出勤日期
 * @param checkStartTime 上班打卡时间
 * @param checkEndTime 下班班打卡时间
 * @param isHalfVocation true 半天出勤。
 * @return 是否有效
 */
export function isEffectWorkTime(workday: string, checkStartTime: string | undefined, checkEndTime: string | undefined, isHalfVocation: boolean, isPM: boolean): boolean {
  const durationInMinutes = getWorkAllTime(workday, checkStartTime, checkEndTime, isPM)
  const isValidDuration = !isHalfVocation ? durationInMinutes >= FULL_DAY_TIME : durationInMinutes >= FULL_HALF_DAY_TIME

  return isValidDuration
}

/**
 * 计算工作日的有效时长
 * 每次工作 4.5 小时需要扣除 0.5 小时的休息时间
 * @param workday 加班日期
 * @param startTime 上班打卡时间
 * @param endTime 下班班打卡时间
 * @return 有效的加班时长
 */
export function calcWeekendWorkMD(workday: string, startTime: string | undefined, endTime: string | undefined) {
  if (startTime === undefined || endTime === undefined)
    return 0
  // 将时间字符串转换为 dayjs 对象
  startTime = convertTo24Hour(startTime)
  endTime = convertTo24Hour(endTime)

  const start = dayjs(`${workday} ${startTime}`)
  const end = dayjs(`${workday} ${endTime}`)

  // 计算总工作时间（以小时为单位）
  const totalDurationHours = NP.divide(end.diff(start, 'minutes'), 60)

  // 每 4.5 小时就减去 0.5 小时的休息时间
  const breakTime = Math.floor(totalDurationHours / 4.5) * 0.5

  // 有效加班时间
  const effectiveWorkHours = totalDurationHours - breakTime

  // 计算 MD（ 1 MD = 8 小时）
  const md = NP.divide(effectiveWorkHours, 8)

  return md
}
